/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.dwh.trigger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.LinkedList;
import static org.dwh.trigger.Log.*;

/**
 *
 * @author Jose Carlos Palma
 */
public class QueueWriter extends Thread {

    /**
     * Almacena informacion sobre la cola (segun el archivo de configuracion).
     *
     * @see org.dwh.trigger.Conf#getQueuesInfo()
     */
    private QueueInfo info;
    /**
     * Almacena informacion del enlace de red con el cliente.
     */
    private Socket client;
    /**
     * Contiene el enlace de escritura con el cliente.
     */
    private PrintWriter pw;
    /**
     * Contiene el enlace de lectura con el cliente.
     */
    private BufferedReader br;
    /**
     * Indica si el hilo se esta o no ejecutando.
     */
    private boolean running = false;
    /**
     * Indica que el hilo termino su ejecucion
     */
    private boolean shutdown = true;
    /**
     * Almacena el ultimo trigger enviado al cliente.
     */
    private Trigger lastPlot;
    /**
     * Contiene el la cola de triggers proveniente de las SLUs
     */
    private LinkedList<Trigger> plots = new LinkedList<Trigger>();

    /**
     *
     * @param info
     */
    public QueueWriter(QueueInfo info) {
        this.info = info;
        setName("Queue - " + info.getName());
    }

    /**
     *
     * @param type
     * @return
     */
    public boolean hasTriggerType(String type) {
        return info.hasType(type);
    }

    /**
     *
     * @param t
     */
    public void addTrigger(Trigger t) {
        synchronized (this) {
            this.plots.add(t);
        }
    }

    /**
     *
     */
    @Override
    public void run() {
        //Verifica si la cola esta activa o inactiva
        if (info.isOff()) {
            info("Queue: " + info.getName() + "[" + info.getStatus() + "]");
            return;
        }

        info("Queue: " + info.getName() + " is starting...");

        try {
            client = new Socket(info.getIp(), info.getPort());
            info("Queue: " + info.getName() + " get output...");
            pw = new PrintWriter(client.getOutputStream(), true);
            info("Queue: " + info.getName() + " get input...");
            br = new BufferedReader(new InputStreamReader(this.client.getInputStream()));
            info("Queue: " + info.getName() + " connect.");
        } catch (UnknownHostException ex) {
            error("Queue: " + info.getName() + " [UnknownHostException] can't to connect, "
                    + (ex.getStackTrace() != null ? ex.getStackTrace()[ex.getStackTrace().length - 1] : ex.getMessage()));
            Runtime.getRuntime().exit(1);
        } catch (IOException ex) {
            error("Queue: " + info.getName() + " [IOException] can't to connect, "
                    + (ex.getStackTrace() != null ? ex.getStackTrace()[ex.getStackTrace().length - 1] : ex.getMessage()));
            Runtime.getRuntime().exit(1);
        }

        this.shutdown = false;
        this.running = true;
        info("Queue: " + info.getName() + " is running...");

        //Ciclo que envia
        while (running && client.isConnected()) {

            try {

                if (plots.isEmpty()) {
                    pause(2000);
                    continue;
                }

                lastPlot = plots.remove();
                pw.println(lastPlot.toPlot());
                trigger(lastPlot);

            } catch (RuntimeException ex) {
                error("Queue: " + info.getName() + " [RuntimeException] can't to connect, "
                        + (ex.getStackTrace() != null ? ex.getStackTrace()[ex.getStackTrace().length - 1] : ex.getMessage()));
                Runtime.getRuntime().exit(1);
            } catch (Exception ex) {
                error("Queue: " + info.getName() + " [RuntimeException] can't to connect, "
                        + (ex.getStackTrace() != null ? ex.getStackTrace()[ex.getStackTrace().length - 1] : ex.getMessage()));
                Runtime.getRuntime().exit(1);
            }
        }

        info("Queue: " + info.getName() + " is shuting down...");

        try {
            client.close();
        } catch (IOException ex) {
        }

        this.shutdown = true;

        info("Queue: " + info.getName() + " is shutdown");
    }

    /**
     *
     */
    public void turnOff() {
        this.running = false;
        try {
            if (client != null) {
                this.client.close();
            }
        } catch (IOException ex) {
        }
    }

    /**
     *
     * @return
     */
    public boolean isShutdown() {
        return this.shutdown;
    }

    /**
     *
     * @return
     */
    public boolean isRunning() {
        return this.running;
    }

    /**
     *
     * @param millis
     */
    public void pause(long millis) {
        try {
            sleep(millis);
        } catch (InterruptedException ex) {
        }
    }

    /**
     *
     * @return
     */
    @Override
    public String toString() {
        return info.toString();
    }

    /**
     * @return the running
     */
    public boolean isConnected() {
        if (client == null) {
            return false;
        }
        return client.isConnected();
    }

    /**
     *
     * @return
     */
    public QueueInfo getInfo() {
        return this.info;
    }

    /**
     *
     * @return
     */
    public String getStatus() {
        return "Queue: " + info.getName() + "[" + info.getIp() + "]: " + lastPlot.getDateName();
    }
}
